package main

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
)

// 定义HTTP请求指标
var (
	httpRequestsTotal = promauto.NewCounterVec(
		prometheus.CounterOpts{
			Name: "http_requests_total",
			Help: "Total number of HTTP requests",
		},
		[]string{"method", "path", "status"},
	)

	httpRequestDuration = promauto.NewHistogramVec(
		prometheus.HistogramOpts{
			Name:    "http_request_duration_seconds",
			Help:    "Duration of HTTP requests in seconds",
			Buckets: prometheus.DefBuckets,
		},
		[]string{"method", "path"},
	)

	httpInFlightRequests = promauto.NewGauge(prometheus.GaugeOpts{
		Name: "http_in_flight_requests",
		Help: "The number of in-flight HTTP requests",
	})
)

func main() {
	mux := http.NewServeMux()

	// 使用中间件收集指标
	mux.HandleFunc("/ip", metricsMiddleware(func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		defer httpRequestDuration.WithLabelValues(r.Method, "/ip").Observe(time.Since(start).Seconds())

		ips, err := getOutboundIPs()
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			httpRequestsTotal.WithLabelValues(r.Method, "/ip", "500").Inc()
			return
		}

		w.Header().Set("Content-Type", "application/json")
		json.NewEncoder(w).Encode(map[string]interface{}{
			"ips":  ips,
			"port": "9999",
			"host": r.Host,
		})
		httpRequestsTotal.WithLabelValues(r.Method, "/ip", "200").Inc()
	}))

	// 健康检查接口
	mux.HandleFunc("/health", metricsMiddleware(func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		defer httpRequestDuration.WithLabelValues(r.Method, "/health").Observe(time.Since(start).Seconds())

		w.WriteHeader(http.StatusOK)
		_, _ = w.Write([]byte("OK"))
		httpRequestsTotal.WithLabelValues(r.Method, "/health", "200").Inc()
	}))

	server := &http.Server{
		Addr:    ":9999",
		Handler: mux,
	}

	shutdown := make(chan os.Signal, 1)
	signal.Notify(shutdown, syscall.SIGINT, syscall.SIGTERM)

	go func() {
		log.Println("http Server started on port 9999")
		_ = server.ListenAndServe()
	}()

	// 如果代码中明确分离指标端口（非必须）
	go func() {
		log.Println("metrics Server started on port 9100")
		metricsServer := &http.Server{Addr: ":9100", Handler: promhttp.Handler()}
		_ = metricsServer.ListenAndServe()
	}()

	<-shutdown
	log.Println("Shutting down server...")

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	if err := server.Shutdown(ctx); err != nil {
		log.Fatalf("Server shutdown failed: %v", err)
	}

	log.Println("Server gracefully shutdown")
}

// 中间件：记录并发请求数
func metricsMiddleware(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		httpInFlightRequests.Inc()
		defer httpInFlightRequests.Dec()
		next(w, r)
	}
}

func getOutboundIPs() ([]string, error) {
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return nil, err
	}

	var ips []string
	for _, addr := range addrs {
		if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if v4 := ipnet.IP.To4(); v4 != nil {
				ips = append(ips, v4.String())
			}
		}
	}

	if len(ips) == 0 {
		return nil, fmt.Errorf("no public IPs found")
	}
	return ips, nil
}
